package com.linwen.javase.juc;

/**
 * @ClassName _10DeadLock
 * @Description
 * @Author lin
 * @Date 2022/4/21 上午1:37
 * @Version V1.0
 *
 * 产生死锁的四个条件：
 * ● 互斥条件：指进程对所分配到的资源进行排它性使用，即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源，则请求者只能等待，直至占有资源的进程用毕释放。
 *
 * ● 请求与保持条件：进程已经保持了至少一个资源，但又提出了新的资源请求，而该资源 已被其他进程占有，此时请求进程被阻塞，但对自己已获得的资源保持不放。
 *
 * ● 不可剥夺条件：进程所获得的资源在未使用完毕之前，不能被其他进程强行夺走，即只能 由获得该资源的进程自己来释放（只能是主动释放)。
 *
 * ● 循环等待条件：指在发生死锁时，必然存在一个进程——资源的环形链，即进程集合{P0，P1，P2，···，Pn}中的P0正在等待一个P1占用的资源；P1正在等待P2占用的资源，……，Pn正在等待已被P0占用的资源。
 解决死锁的思路：
只要打破四个必要条件之一就能有效预防死锁的发生：

● 打破互斥条件：改造独占性资源为虚拟资源，大部分资源已无法改造。

● 打破不可抢占条件：当一进程占有一独占性资源后又申请一独占性资源而无法满足，则退出原占有的资源。

● 打破占有且申请条件：采用资源预先分配策略，即进程运行前申请全部资源，满足则运行，不然就等待，这样就不会占有且申请。

● 打破循环等待条件：实现资源有序分配策略，对所有设备实现分类编号，所有进程只能采用按序号递增的形式申请资源。

 * jps：显示当前所有java进程pid的命令
 * jstack pid: 发现是否有死锁产生
 */
public class _10DeadLock {
    private static final Object a = new Object();
    private static final Object b = new Object();

    public static void main(String[] args) {
        new Thread(()->{
            synchronized (a){
                System.out.println(Thread.currentThread().getName()+"获得锁a");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (b){
                    System.out.println(Thread.currentThread().getName()+"获得锁b");
                }
            }
        },"a").start();
        new Thread(()->{
            synchronized (b){
                System.out.println(Thread.currentThread().getName()+"获得锁b");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (a){
                    System.out.println(Thread.currentThread().getName()+"获得锁a");
                }
            }
        },"a").start();
    }
}
